-- Script/Unit.lua
-- 角色基本属性定义模块 - 修改翻滚参数

local Unit = {}
Unit.__index = Unit

local definitionCache = {}

function Unit.getDefinition(characterId)
    if definitionCache[characterId] then
        return definitionCache[characterId]
    end
    
    if not Platformer then
        definitionCache[characterId] = Unit.getDefaultDefinition()
        return definitionCache[characterId]
    end
    
    local unitDef = Platformer.Data.store["Unit:" .. characterId]
    if not unitDef then
        unitDef = Platformer.Data.store["Unit:player"]
    end
    
    if not unitDef then
        definitionCache[characterId] = Unit.getDefaultDefinition()
    else
        definitionCache[characterId] = unitDef
    end
    
    return definitionCache[characterId]
end

function Unit.getDefaultDefinition()
    return {
        hp = 5.0,
        bodyType = "Dynamic",
        scale = 1.0,
        density = 1.0,
        friction = 1.0,
        restitution = 0.0,
        
        move = 380,
        sprintMove = 1300,
        acceleration = 7500,
        deceleration = 1425,
        airControl = 0.8,
        friction = 0.7,
        airResistance = 0.998,
        
        jump = 1300,
        jumpSpeed = 1475,
        multiJumpSpeed = 1450,
        jumpBufferTime = 0.15,
        coyoteTime = 0.15,
        maxFallSpeed = 2800,
        
        detectDistance = 350,
        attackDistance = 1200,
        attackCooldown = 0.3,
        attackSpeed = 900,
        usePreciseHit = false,
        sensity = 0,
        
        -- 修改翻滚参数
        rollSpeed = 3200,               -- 降低翻滚速度
        rollDistance = 1100,
        rollDuration = 1.4,
        rollCooldown = 0.1,
        rollInvincibleTime = 0.15,     -- 缩短无敌时间到0.15秒
        
        playable = "spine:Spine/moling",
        size = {width = 60, height = 300},
        defaultFaceRight = true,
        
        tag = "player",
        decisionTree = "AI:playerControl",
        
        actions = {"idle", "turn", "move", "jump", "fallOff", "cancel", "roll"}
    }
end

function Unit.create(characterId)
    local definition = Unit.getDefinition(characterId)
    
    return {
        characterId = characterId,
        definition = definition,
        
        currentHealth = definition.hp,
        maxHealth = definition.hp,
        isAlive = true,
        
        isMoving = false,
        isGrounded = true,
        isSprinting = false,
        isJumping = false,
        isRolling = false,
        isInvincible = false,
        
        position = {x = 0, y = 0},
        velocity = {x = 0, y = 0},
        facingDirection = definition.defaultFaceRight and 1 or -1,
        
        moveState = "idle",
        jumpState = "grounded",
        currentAction = "idle",
        
        canAttack = true,
        attackCooldown = 0,
        
        canDoubleJump = false,
        hasDoubleJumped = false,
        jumpBuffer = 0,
        coyoteTimer = 0
    }
end

function Unit.getMoveSpeed(unitInstance)
    local definition = unitInstance.definition
    if unitInstance.isSprinting then
        return definition.sprintMove or 600
    else
        return definition.move or 300
    end
end

function Unit.getJumpForce(unitInstance)
    return unitInstance.definition.jump or 1000
end

function Unit.getJumpSpeed(unitInstance)
    return unitInstance.definition.jumpSpeed or 650
end

function Unit.getMultiJumpSpeed(unitInstance)
    return unitInstance.definition.multiJumpSpeed or 500
end

function Unit.getJumpBufferTime(unitInstance)
    return unitInstance.definition.jumpBufferTime or 0.15
end

function Unit.getCoyoteTime(unitInstance)
    return unitInstance.definition.coyoteTime or 0.15
end

function Unit.getMaxFallSpeed(unitInstance)
    return unitInstance.definition.maxFallSpeed or 1200
end

function Unit.getDetectDistance(unitInstance)
    return unitInstance.definition.detectDistance or 350
end

function Unit.getAttackDistance(unitInstance)
    return unitInstance.definition.attackDistance or 1200
end

function Unit.getAttackCooldown(unitInstance)
    return unitInstance.definition.attackCooldown or 0.3
end

function Unit.getAttackSpeed(unitInstance)
    return unitInstance.definition.attackSpeed or 900
end

function Unit.getAcceleration(unitInstance)
    return unitInstance.definition.acceleration or 5000
end

function Unit.getDeceleration(unitInstance)
    return unitInstance.definition.deceleration or 850
end

function Unit.getAirControl(unitInstance)
    return unitInstance.definition.airControl or 0.8
end

function Unit.getFriction(unitInstance)
    return unitInstance.definition.friction or 0.7
end

function Unit.getAirResistance(unitInstance)
    return unitInstance.definition.airResistance or 0.998
end

function Unit.getRollSpeed(unitInstance)
    return unitInstance.definition.rollSpeed or 400
end

function Unit.getRollDistance(unitInstance)
    return unitInstance.definition.rollDistance or 160
end

function Unit.getRollDuration(unitInstance)
    return unitInstance.definition.rollDuration or 0.4
end

function Unit.getRollCooldown(unitInstance)
    return unitInstance.definition.rollCooldown or 0.1
end

function Unit.getRollInvincibleTime(unitInstance)
    return unitInstance.definition.rollInvincibleTime or 0.15
end

function Unit.applyDamage(unitInstance, damage)
    if not unitInstance.isAlive then
        return false
    end
    
    if unitInstance.isInvincible then
        return false
    end
    
    unitInstance.currentHealth = math.max(0, unitInstance.currentHealth - damage)
    
    if unitInstance.currentHealth <= 0 then
        unitInstance.isAlive = false
        unitInstance.currentAction = "cancel"
    end
    
    return true
end

function Unit.heal(unitInstance, amount)
    if not unitInstance.isAlive then
        return false
    end
    
    unitInstance.currentHealth = math.min(unitInstance.maxHealth, unitInstance.currentHealth + amount)
    return true
end

function Unit.reset(unitInstance)
    local definition = unitInstance.definition
    
    unitInstance.currentHealth = definition.hp
    unitInstance.maxHealth = definition.hp
    unitInstance.isAlive = true
    unitInstance.isMoving = false
    unitInstance.isGrounded = true
    unitInstance.isSprinting = false
    unitInstance.isJumping = false
    unitInstance.isRolling = false
    unitInstance.isInvincible = false
    unitInstance.position = {x = 0, y = 0}
    unitInstance.velocity = {x = 0, y = 0}
    unitInstance.facingDirection = definition.defaultFaceRight and 1 or -1
    unitInstance.moveState = "idle"
    unitInstance.jumpState = "grounded"
    unitInstance.currentAction = "idle"
    unitInstance.canAttack = true
    unitInstance.attackCooldown = 0
    unitInstance.canDoubleJump = false
    unitInstance.hasDoubleJumped = false
    unitInstance.jumpBuffer = 0
    unitInstance.coyoteTimer = 0
end

function Unit.isActionAvailable(unitInstance, action)
    local definition = unitInstance.definition
    for _, availableAction in ipairs(definition.actions) do
        if availableAction == action then
            return true
        end
    end
    return false
end

function Unit.getSize(unitInstance)
    return unitInstance.definition.size or {width = 60, height = 300}
end

local radiusCache = {}
function Unit.getRadius(unitInstance)
    local characterId = unitInstance.characterId
    if radiusCache[characterId] then
        return radiusCache[characterId]
    end
    
    local size = Unit.getSize(unitInstance)
    local radius = math.max(size.width, size.height) / 2
    radiusCache[characterId] = radius
    return radius
end

function Unit.clearCache()
    definitionCache = {}
    radiusCache = {}
end

return Unit